package com.slipper.system.codeless.service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import com.slipper.core.cache.CacheKey;
import com.slipper.core.cache.CacheUtil;
import com.slipper.core.message.MessageUtil;
import com.slipper.core.message.Topic;
import com.slipper.util.Tool;
import com.slipper.util.UUID;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;

import com.slipper.system.codeless.dao.PageCompDao;
import com.slipper.system.codeless.bo.PageCompBO;

import com.slipper.core.transaction.ReadTransactional;
import com.slipper.core.transaction.WriteTransactional;

@Service
@ReadTransactional
public class PageCompService {
    @Resource
    private PageCompDao pageCompDao;
    @Resource
    private PageCompParamService pageCompParamService;
    @Resource
    private PageCompButtonService pageCompButtonService;
    @Resource
    private PageCompFilterService pageCompFilterService;
    @Resource
    private PrivilegeService privilegeService;

    public PageCompBO queryBy(String id) {
        if (Tool.isBlank(id)) {
            return null;
        }

        PageCompBO pageComp = CacheUtil.get(CacheKey.PageComp.PREFIX + id, PageCompBO.class);
        if (pageComp == null) {
            pageComp = pageCompDao.queryBy(id);
            pageComp.setParamList(pageCompParamService.queryByCompId(id));
            pageComp.setButtonList(pageCompButtonService.queryByCompId(id));
            pageComp.setFilterList(pageCompFilterService.queryByCompId(id));
            pageComp.setPrivilegeList(privilegeService.queryBySourceId(id));
            CacheUtil.set(CacheKey.PageComp.PREFIX + id, pageComp, 60 * 60);
        }
        return pageComp;
    }
    
    public List<PageCompBO> queryList(PageCompBO bo) {
        return pageCompDao.queryList(bo);
    }

    public Map<String, String> queryCompPageList() {
        Map<String, String> resultMap = new HashMap<>();
        List<Map<String, Object>> pageCompList = pageCompDao.queryCompPageList();
        pageCompList.forEach(entry -> resultMap.put((String) entry.get("id"), (String) entry.get("page_id")));
        return resultMap;
    }

    public List<PageCompBO> queryListBy(String[] pageIds) {
        return pageCompDao.queryListBy(pageIds);
    }

    public PageInfo<PageCompBO> queryPage(PageCompBO bo) {
        PageHelper.startPage(bo.getPageNumber(), bo.getPageSize());
        return new PageInfo<>(pageCompDao.queryList(bo));
    }

    @WriteTransactional
    public int save(PageCompBO bo) {
        if (Tool.isBlank(bo.getId())) {
            bo.setId(UUID.getUUID());
            bo.setUpdateTime(System.currentTimeMillis());
            bo.setCreateTime(System.currentTimeMillis());
            pageCompDao.insert(bo);
        } else {
            bo.setUpdateTime(System.currentTimeMillis());
            pageCompDao.update(bo);
        }

        pageCompParamService.save(bo.getId(), bo.getParamList(), bo.getUpdateId());
        pageCompButtonService.save(bo.getId(), bo.getButtonList(), bo.getUpdateId());
        pageCompFilterService.save(bo.getId(), bo.getFilterList(), bo.getUpdateId());
        privilegeService.save(bo.getId(), bo.getPrivilegeList(), bo.getUpdateId());

        CacheUtil.remove(CacheKey.PageComp.PREFIX + bo.getId());
        CacheUtil.remove(CacheKey.Page.PREFIX + bo.getPageId());

        MessageUtil.publish(Topic.PAGE_COMP_CHANGE);

        return 1;
    }

    @WriteTransactional
    public void saveList(List<PageCompBO> list) {
        if (list == null) return;

        list.forEach(item -> {
            if (pageCompDao.queryBy(item.getId()) != null) {
                item.setUpdateTime(System.currentTimeMillis());
                pageCompDao.update(item);
            } else {
                item.setUpdateTime(System.currentTimeMillis());
                item.setCreateTime(System.currentTimeMillis());
                pageCompDao.insert(item);
            }
            CacheUtil.remove(CacheKey.PageComp.PREFIX + item.getId());
            CacheUtil.remove(CacheKey.Page.PREFIX + item.getPageId());
        });
    }
    
    @WriteTransactional
    public int save(String pageId, List<PageCompBO> list, String employeeId) {
        if (Tool.isBlank(pageId)) {
            return 0;
        }

        for (int i=0;i<list.size(); i++) {
            PageCompBO comp = list.get(i);
            comp.setPageId(pageId);
            comp.setOrdinal(i);
            if (Tool.isBlank(comp.getId())) {
                comp.setId(UUID.getUUID());
                comp.setUpdateId(employeeId);
                comp.setCreateId(employeeId);
                comp.setUpdateTime(System.currentTimeMillis());
                comp.setCreateTime(System.currentTimeMillis());
                pageCompDao.insert(comp);
            } else {
                comp.setUpdateId(employeeId);
                pageCompDao.update(comp);
            }

            pageCompParamService.save(comp.getId(), comp.getParamList(), employeeId);
            pageCompButtonService.save(comp.getId(), comp.getButtonList(), employeeId);
            pageCompFilterService.save(comp.getId(), comp.getFilterList(), employeeId);
            privilegeService.save(comp.getId(), comp.getPrivilegeList(), employeeId);

            CacheUtil.remove(CacheKey.PageComp.PREFIX + comp.getId());
            CacheUtil.remove(CacheKey.Page.PREFIX + comp.getPageId());
        }

        // 删除被删除的数据
        PageCompBO qo = new PageCompBO();
        qo.setPageId(pageId);
        pageCompDao.queryList(qo).stream()
                .filter(comp -> list.stream().noneMatch(temp -> comp.getId().equals(temp.getId())))
                .forEach(this::delete);
        return 1;
    }

    @WriteTransactional
    public void deleteByPageId(String pageId) {
        if (Tool.isBlank(pageId)) {
            return;
        }

        PageCompBO qo = new PageCompBO();
        qo.setPageId(pageId);
        pageCompDao.queryList(qo).forEach(this::delete);
    }
    
    @WriteTransactional
    public int delete(PageCompBO bo) {
        pageCompParamService.deleteByCompId(bo.getId());
        pageCompButtonService.deleteByCompId(bo.getId());
        pageCompFilterService.deleteByCompId(bo.getId());
        privilegeService.deleteBySourceId(bo.getId());
        int result = pageCompDao.delete(bo.getId());
        CacheUtil.remove(CacheKey.PageComp.PREFIX + bo.getId());
        CacheUtil.remove(CacheKey.Page.PREFIX + bo.getPageId());
        return result;
    }

    public List<PageCompBO> queryByPageId(String pageId) {
        PageCompBO qo = new PageCompBO();
        qo.setPageId(pageId);
        List<PageCompBO> pageCompList = pageCompDao.queryList(qo);

        pageCompList.forEach(pageComp -> {
            pageComp.setParamList(pageCompParamService.queryByCompId(pageComp.getId()));
            pageComp.setButtonList(pageCompButtonService.queryByCompId(pageComp.getId()));
            pageComp.setFilterList(pageCompFilterService.queryByCompId(pageComp.getId()));
            pageComp.setPrivilegeList(privilegeService.queryBySourceId(pageComp.getId()));
        });
        return pageCompList;
    }

    @WriteTransactional
    public void copyByPageId(String oldPageId, String newPageId, String employeeId, Map<String, String> paramMap) {
        if (Tool.isBlank(oldPageId)) {
            return;
        }

        queryByPageId(oldPageId).forEach(comp -> {
            String oldCompId = comp.getId();
            PageCompBO pageComp = pageCompDao.queryBy(oldCompId);

            pageComp.setId(UUID.getUUID());
            pageComp.setPageId(newPageId);
            pageComp.setUpdateId(employeeId);
            pageComp.setCreateId(employeeId);
            pageComp.setUpdateTime(System.currentTimeMillis());
            pageComp.setCreateTime(System.currentTimeMillis());
            pageCompDao.insert(pageComp);

            pageCompParamService.copyByCompId(oldCompId, pageComp.getId(), employeeId, paramMap);
            pageCompButtonService.copyByCompId(oldCompId, pageComp.getId(), employeeId);
            pageCompFilterService.copyByCompId(oldCompId, pageComp.getId(), employeeId);
            privilegeService.copyBySourceId(oldCompId, pageComp.getId(), employeeId);
        });
    }
}
